package net.biodiversityatlas.umap
{
   import com.afcomponents.umap.providers.TileLayer;
   import com.afcomponents.umap.types.LatLng;
   
   import flash.geom.Point;
   
   // this class extends the abstract TileLayer class
   // it adds servers, and defines the path to our tiles
   
   public class WMSLayer extends TileLayer {
	  public var baseServerUrl:String;
	  public var layers:String;
	  public var styles:String;
	  public var filter:String;	  
	  private var MAGIC_NUMBER:Number=6378137.0;
	  
	  //Needed for transformations
	  private var offset:Number=16777216;
	  private var radius:Number=offset / Math.PI; 

      public function WMSLayer(baseServerUrl:String, layers:String, styles:String, filter:String)
      {

      	this.baseServerUrl = baseServerUrl;
      	this.layers = layers;
      	this.styles = styles;
      	this.filter = filter;
      	
      	//construct the base URL
      	var urlBase:String = baseServerUrl + 
      						"FORMAT=image%2Fpng&SERVICE=WMS&REQUEST=GetMap&WIDTH=256&HEIGHT=256&VERSION=1.0.0&TRANSPARENT=true&" +
      						"STYLES=" + styles + "&" +
      						"LAYERS="+ layers + "&" +
      						"FILTER="+ filter + "&";

         super("[server]", 0, 17, true, "");
         
         this.addServer(urlBase);
         this.addServer(urlBase);
         this.addServer(urlBase);
         this.addServer(urlBase);
      }
      
      // return path to the requested tile
      override public function getTileURL(tile:Point, zoom:uint):String
      {
      	//Adjust the zoom level from the new to the old, as the server side tiles depend on the old one.
      	var zoomLevel:Number = 17 - zoom;
      	
      	//LowerLeft Corner
		var tileIndexLL:Point = new Point(256*tile.x, 256*(tile.y+1));
		//UpperRight Corner
		var tileIndexUR:Point = new Point(256*(tile.x+1), 256*(tile.y));
		
		var SRS:String = 'EPSG%3A900913';
		
		var bbox:String;
		var LL:LatLng = new LatLng(YToL(zoomLevel,tileIndexLL.y),XToL(zoomLevel,tileIndexLL.x));
		var UR:LatLng = new LatLng(YToL(zoomLevel,tileIndexUR.y),XToL(zoomLevel,tileIndexUR.x));
		
		bbox =  dd2MercMetersLng(LL.lngRadians)+","+dd2MercMetersLat(LL.latRadians) + "," + dd2MercMetersLng(UR.lngRadians)+","+dd2MercMetersLat(UR.latRadians);

    	var wmsUrl:String = "[server]SRS="+SRS+"&BBOX=" + bbox;

		return wmsUrl;
      }    
	  
		private function dd2MercMetersLng(p_lng:Number):Number { 
			return Number((MAGIC_NUMBER * p_lng).toFixed(4)); 
		}
		
		private function dd2MercMetersLat(p_lat:Number):Number {
			if (p_lat >= 85) p_lat=85;
			if (p_lat <= -85) p_lat=-85;
			return Number((MAGIC_NUMBER * Math.log(Math.tan(p_lat / 2 + Math.PI / 4))).toFixed(4));
		}   
	    
	    
	  
	  //TRANSFORMATION EQUATIONS FROM PIXEL TO LATLON
		private function LToX(z:Number,x:Number):Number {
			return (offset+radius*x*Math.PI/180)>>z;
		}

		private function LToY(z:Number,y:Number):Number {
			return (offset-radius*Math.log((1+Math.sin(y*Math.PI/180))/(1-Math.sin(y*Math.PI/180)))/2)>>z;
		}

		private function XToL(z:Number,x:Number):Number {
        	return (((x<<z)-offset)/radius)*180/Math.PI;
		}

		private function YToL(z:Number,y:Number):Number {
		    return (Math.PI/2-2*Math.atan(Math.exp(((y<<z)-offset)/radius)))*180/Math.PI;
		} 
	  
          
   }
}